package com.sjb.sixteen_journey_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sjb.sixteen_journey_backend.common.CommonHandle;
import com.sjb.sixteen_journey_backend.common.ImagesProperties;
import com.sjb.sixteen_journey_backend.common.R;
import com.sjb.sixteen_journey_backend.entity.Follower;
import com.sjb.sixteen_journey_backend.entity.User;
import com.sjb.sixteen_journey_backend.entity.dto.LoginDto;
import com.sjb.sixteen_journey_backend.entity.dto.UpdatePwdDto;
import com.sjb.sixteen_journey_backend.handler.exception.CustomException;
import com.sjb.sixteen_journey_backend.mapper.UserMapper;
import com.sjb.sixteen_journey_backend.service.IFollowerService;
import com.sjb.sixteen_journey_backend.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sjb.sixteen_journey_backend.utils.AliOssUtil;
import com.sjb.sixteen_journey_backend.utils.JwtUtil;
import com.sjb.sixteen_journey_backend.utils.RedisUtil;
import com.sjb.sixteen_journey_backend.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author jcz
 * @since 2024-06-24
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    //密码加密
    private static final String SALT = "sixteenjourneybackend";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private IFollowerService followerService;



    @Override
    public R isExistUserName(String username) {
        try {
            //查询用户
            Map<String, Object> columnMap = new HashMap<>();
            columnMap.put("username", username);
            List<User> users = this.listByMap(columnMap);
            if (users.size() > 0) {
                //占用
                return R.error("用户名已被占用", 400);
            } else {
                return R.success("用户名可用", 200);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R register(User user) {

        try {
            String perPassword = user.getPassword();
            //查询用户
            Map<String, Object> columnMap = new HashMap<>();
            columnMap.put("username", user.getUsername());
            List<User> users = this.listByMap(columnMap);
            if (users.size() > 0) {
                //占用
                return R.error("用户名已被占用", 400);
            } else {
                String password = user.getPassword();
                password = DigestUtils.md5DigestAsHex((SALT + password).getBytes());//MD5进行加密 Md5Util.getMD5String(password);
                user.setPassword(password);

                boolean save = this.save(user);
                if (save) {
                    LoginDto loginDto = new LoginDto(user.getUsername(), perPassword);
                    R<User> login = this.login(loginDto);
                    return login;
                } else {
                    return R.error("注册失败", 404);
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return R.error("注册失败", 404);
        }
    }


    @Override
    public R<User> login(LoginDto loginDto) throws Exception {
        R<User> result = new R<>();
        try {
            String password = loginDto.getPassword();
            //MD5进行加密
            password = DigestUtils.md5DigestAsHex((SALT + password).getBytes());
//            select * from User where username = loginDto.getName or phone = loginDto.getName or email = loginDto.getEmail
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", loginDto.getName())
                    .or()
                    .eq("phone", loginDto.getName())
                    .or()
                    .eq("email", loginDto.getName());
            User user = userMapper.selectOne(queryWrapper);
            //如果为空则创建
            if (null == user) {
                return R.error("手机号、用户名、邮箱错误或者请注册该用户！");
            } else {
//                log.info("用户信息：" + password);
//                log.info("用户信息2：" + user.getPassword());
                if (!password.equals(user.getPassword())) {
                    return R.error("密码错误，登录失败！");
                }
                //获取用户的token值
                Map<String, Object> claims = new HashMap<>();
                claims.put("id", user.getUserId());
                claims.put("username", user.getUsername());
                String token = JwtUtil.genToken(claims);

                //用于修改密码 把token存储到redis中
                ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
                operations.set(token, token, 24, TimeUnit.HOURS);//过期时间为1天
//                ValueOperations<String, String> operations  = redisTemplate.opsForValue();
//                operations.set(token, token, 24, TimeUnit.HOURS);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                //返回成功信息
                result.add("token", token);
                result.setMsg("登录成功");
                result.setCode(200);
                result.setData(user);
                log.info("token:" + token);
                return result;
            }
        } catch (Exception e) {
            log.info("登录失败:" + e);
//            throw new Exception(e);
            return R.error("登录失败！");
        }
    }

    @Override
    public R updatePwd(UpdatePwdDto updatePwdDto) {
        //1.校验参数
        String oldPwd = updatePwdDto.getOldPwd();
        String newPwd = updatePwdDto.getNewPwd();
        String rePwd = updatePwdDto.getRePwd();

        try {
            if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)) {
                return R.error("缺少必要的参数", 400);
            }

            //原密码是否正确
            //调用userService根据用户名拿到原密码,再和old_pwd比对
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User loginUser = userMapper.selectById(id);
            if (!loginUser.getPassword().equals(DigestUtils.md5DigestAsHex((SALT + oldPwd).getBytes()))) {
                return R.error("原密码填写不正确", 400);
            }
            //newPwd和rePwd是否一样
            if (!rePwd.equals(newPwd)) {
                return R.error("两次填写的新密码不一样", 400);
            }
            //2.调用service完成密码更新
            UpdateWrapper<User> update = Wrappers.update();
            update.eq("user_id", id)
                    .set("password", DigestUtils.md5DigestAsHex((SALT + newPwd).getBytes()));
            userMapper.update(null, update);
            //删除redis中对应的token
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            operations.getOperations().delete(token);


            return R.success(null, "密码修改成功，请重新登录！");
        } catch (Exception e) {
            log.info(e.getMessage());
            return R.error("密码更新失败");
        }
    }

    @Override
    public R deleteUser() {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User user = userMapper.selectById(id);
            if (user != null && userMapper.deleteById(id) > 0) {
                ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
                operations.getOperations().delete(token);

//                String rootPath = System.getProperty("user.dir") + imagesProperties.getRootPath()+imagesProperties.getAvatar();
//                //先获取图片名
//                String img = user.getAvatar().substring(user.getAvatar().lastIndexOf('/') + 1);
//                //先删除原来的图片
//                File f = new File(rootPath + img);
//                f.delete();

                return R.success(null, "删除成功！");

            } else {
                return R.error("删除失败！");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<User> updateUserAvatar(MultipartFile file) {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");

            String path = file.getOriginalFilename();
//            String rootPath = System.getProperty("user.dir") + imagesProperties.getRootPath()+imagesProperties.getAvatar();

            User user = userMapper.selectById(id);
            if (user != null) {
                //获得新传入的图片名，修改图片名为唯一的
                String fileName = UUID.randomUUID().toString() + path.substring(path.lastIndexOf("."));
                /*
                //先获取图片名
                String img = user.getAvatar().substring(user.getAvatar().lastIndexOf('/') + 1);
                //先删除原来的图片
                 File f = new File(rootPath + img);
                f.delete();
                file.transferTo(new File(rootPath + fileName));
                user.setAvatar(imagesProperties.getVisitImagePath()+imagesProperties.getAvatar() + fileName);*/

                //存储在阿里云云服务器上 oss
                String url = AliOssUtil.uploadFile(fileName,file.getInputStream());
                user.setAvatar(url);
                userMapper.updateById(user);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                return R.success(user, "修改用户头像成功！");
            } else {
                return R.error("修改用户头像失败！");
            }
        } catch (Exception e) {
            return R.error("修改用户头像失败！");
        }
    }

    @Override
    public R<User> getUserByUserNameOrPhone(String data) {
        try {
            if (StringUtils.hasLength(data)) {
                QueryWrapper<User> wrapper = Wrappers.query();
                wrapper.like("username", "%" + data + "%").or().eq("phone", data);
                User user = userMapper.selectOne(wrapper);
                if (user != null) {
                    User userWithoutPassword = user.withoutPassword();
                    return R.success(userWithoutPassword, "查询成功！");
                }
            }
            return R.error("查询失败！");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public User getUserById(Integer id) {
        try {
            User user = this.getById(id);
            //返回关注量和粉丝量
            user = this.getFollowsAndFans(user);
            user = user.withoutPassword();
            return user;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    @Override
    public R<User> updateUserUsername(String username) {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User user = userMapper.selectById(id);
            if (user != null) {
                user.setUsername(username);
                userMapper.updateById(user);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                return R.success(user, "修改用户名成功！");
            } else {
                return R.error("修改用户名失败！");
            }
        } catch (Exception e) {
            return R.error("修改用户名失败！");
        }
    }

    @Override
    public R<User> updateUserGender(Integer gender) {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User user = userMapper.selectById(id);
            if (user != null) {
                user.setGender(gender);
                userMapper.updateById(user);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                return R.success(user, "修改用户性别成功！");
            } else {
                return R.error("修改用户性别失败！");
            }
        } catch (Exception e) {
            return R.error("修改用户性别失败！");
        }
    }

    @Override
    public R<User> updateUserAddress(String address) {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User user = userMapper.selectById(id);
            if (user != null) {
                user.setAddress(address);
                userMapper.updateById(user);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                return R.success(user, "修改用户常住地成功！");
            } else {
                return R.error("修改用户常住地失败！");
            }
        } catch (Exception e) {
            return R.error("修改用户常住地失败！");
        }
    }

    @Override
    public R<User> updateUserSignature(String signature) {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer id = (Integer) map.get("id");
            String token = (String) map.get("token");
            User user = userMapper.selectById(id);
            if (user != null) {
                user.setSignature(signature);
                userMapper.updateById(user);

                //返回关注量和粉丝量
                user = this.getFollowsAndFans(user);
                user = user.withoutPassword();

                return R.success(user, "修改用户签名成功！");
            } else {
                return R.error("修改用户签名失败！");
            }
        } catch (Exception e) {
            return R.error("修改用户签名失败！");
        }
    }

    public User getFollowsAndFans(User user) {
        //查询粉丝量和关注量
        QueryWrapper<Follower> wrapper = Wrappers.query();
        //关注量
        wrapper.eq("user_id", user.getUserId());
        int count = (int) followerService.count(wrapper);
        user.setFollowers(count);
        wrapper.clear();
        //粉丝量
        wrapper.eq("fans_id", user.getUserId());
        count = (int) followerService.count(wrapper);
        user.setFans(count);
        return user;
    }


}
